package loader

import (
	"strings"
)

type ReadType string

const (
	EXCEL ReadType = "excel"
	CSV   ReadType = "csv"
	AJSON ReadType = "ajson"
)

type DesignFile struct {
	Name           string //文件名
	SubName        string //子文件名，用在如excel多sheet页的情况
	ClassName      string //导出的类名
	Macros         []string
	Fields         []*DesignField
	Datas          [][]string
	ExportTags     []string
	OutputNameType string
	NameRow        int
	TypeRow        int
	TagRow         int
	CommentRow     int
}

type DesignField struct {
	FieldName    string
	FieldType    string
	FieldTags    []string
	FieldComment string
}

func NewDesignFile(fileName string, rows [][]string) *DesignFile {
	fileName = strings.Replace(fileName, "\\", "", -1)
	fileName = strings.Replace(fileName, "/", "", -1)
	fileName = strings.Replace(fileName, ":", "", -1)
	fileName = strings.Replace(fileName, "*", "", -1)
	fileName = strings.Replace(fileName, "?", "", -1)
	fileName = strings.Replace(fileName, "\"", "", -1)
	fileName = strings.Replace(fileName, "<", "", -1)
	fileName = strings.Replace(fileName, ">", "", -1)
	fileName = strings.Replace(fileName, "|", "", -1)

	var dFile DesignFile
	dFile.Name = fileName

	firstRowNum := dFile.determineFirstRowNum(rows)

	macros := rows[firstRowNum]
	dFile.FillMacro(macros)

	var nameRow []string
	var typeRow []string
	var tagRow []string
	var commentRow []string
	for i, row := range rows {
		if row[0] == "#tag" {
			tagRow = row
			dFile.TagRow = i
		} else if row[0] == "#type" {
			typeRow = row
			dFile.TypeRow = i
		} else if row[0] == "#name" {
			nameRow = row
			dFile.NameRow = i
		} else if row[0] == "#comment" {
			commentRow = row
			dFile.CommentRow = i
		}
	}
	dFile.FillField(nameRow, typeRow, tagRow, commentRow)
	dFile.FillData(rows[firstRowNum+5:])
	return &dFile
}

func (d *DesignFile) determineFirstRowNum(rows [][]string) int {
	for i, row := range rows {
		if strings.HasPrefix(row[0], "#") {
			return i
		}
	}
	panic("未找到数据表格的开始定义#")
}

func (d *DesignFile) FillMacro(macros []string) {
	d.Macros = make([]string, 0)
	for _, v := range macros {
		if v != "" {
			d.Macros = append(d.Macros, v)
		}
		if strings.HasPrefix(v, "#name") {
			parts := strings.Split(v, " ")
			d.ClassName = strings.TrimSpace(parts[1])

		} else if strings.HasPrefix(v, "#export") {
			parts := strings.Split(v, " ")
			for i, part := range parts {
				if i <= 0 {
					continue
				}
				d.ExportTags = append(d.ExportTags, part)
			}
		}
	}
	if d.ClassName == "" {
		//TODO 抛异常
		panic("未定义类名")
	}
}

func (d *DesignFile) FillField(names []string, types []string, tags []string, comments []string) {
	size := len(names)
	if len(types) > size || len(tags) > size || len(comments) > size {
		panic("格式错误的配置表，未定义整齐的表头" + d.Name)
	}

	for i := range names {
		if i <= 0 {
			continue
		}
		if names[i] == "" {
			break
		}
		var field DesignField
		field.FieldName = names[i]
		field.FieldType = types[i]
		field.FieldTags = strings.Split(tags[i], ",")
		field.FieldComment = comments[i]
		d.Fields = append(d.Fields, &field)
	}
}

func (d *DesignFile) FillData(rowDatas [][]string) {
	d.Datas = make([][]string, 0, len(rowDatas))
	for _, row := range rowDatas {
		if len(row) <= 1 || row[1] == "" {
			//首列被#tag、#type、#name、#comment等的宏定义占用了，数据列从第二列开始，如果为空则不导出
			continue
		}
		allEmpty := true
		for i, v := range row {
			if i <= 0 {
				continue
			}
			if v != "" {
				allEmpty = false
				break
			}
		}
		if !allEmpty {
			d.Datas = append(d.Datas, row[1:])
		}
	}
}

// 获取文件输出时使用的名字
func (d *DesignFile) GetOutputName() string {
	if d.OutputNameType == "useFileName" {
		return d.Name
	} else {
		return d.ClassName
	}
}

// 是否需要导出
func (d *DesignFile) FileNeedExport(tags [][]string) bool {
	if len(d.ExportTags) == 0 {
		return true
	}
	return FieldNeedExport(d.ExportTags, tags)
}

// defineTags 定义标签
// expectTags 期望标签
func FieldNeedExport(defineTags []string, expectTags [][]string) bool {
	if len(defineTags) == 1 && defineTags[0] == "*" {
		return true
	} else if len(defineTags) == 1 && defineTags[0] == "-" {
		//TODO 这里要改成false
		return true
	}
	for _, vv := range expectTags {
		match := true
		for _, v := range vv {
			find := false
			for _, dTags := range defineTags {
				if dTags == v {
					find = true
				}
			}
			if !find {
				match = false
			}
		}
		if match {
			return true
		}
	}
	return false
}
